home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 6 / MacMania 6.toast / / Multimedia & Desktop / sk8 / SK8InJava / Code / Actors / Actor.java next >
Encoding:
Java Source  |  1997-02-27  |  38.3 KB  |  1,398 lines  |  [TEXT/CWIE]

  1. /*  SK8 © 1997 Apple Computer, Inc.
  2.     This code is protected under the current SK8 License
  3.     See http://sk8.research.apple.com/ for more information
  4.     Apple Research Laboratories
  5. */
  6.  
  7.  
  8. import java.awt.*;
  9. import java.applet.Applet;
  10.  
  11. public class actor {
  12.  
  13.     //======================================================================
  14.     // constants. 
  15.     //======================================================================
  16.         
  17.     public static boolean debug = false; 
  18.         
  19.     // A mousedowneventmode that keeps getting reused. 
  20.     static mousedowneventmode mousetrackingmode = new mousedowneventmode();
  21.  
  22.     //======================================================================
  23.     // slots. 
  24.     //======================================================================
  25.     
  26.     public int filldirty = 0;
  27.     public int framedirty = 0;
  28.     
  29.     
  30.      renderer fillcolorVar = sk8.white;
  31.     renderer framecolorVar = sk8.black;
  32.     renderer textcolorVar = sk8.black;
  33.     
  34.     int framesizeVar = 1;
  35.     
  36.     String textVar = "";
  37.     Font textfontVar;
  38.     symbol textlocationVar = sk8.quote("CENTER");
  39.         
  40.     
  41.     //======================================================================
  42.     // Methods. 
  43.     //======================================================================
  44.     
  45.     public actor() {
  46.         super();
  47.         this.textfontVar = new Font("Geneva", Font.PLAIN, 9);
  48.         this.boundsrectVar = new Rectangle(0,0,20,20);
  49.         this.contentsVar = new list();
  50.         this.regionsDirty = true;
  51.     }
  52.                 
  53.     //======================================================================
  54.     // locking, making dirty, etc. Low level stuff. 
  55.     //======================================================================
  56.  
  57.     public stage stage () {
  58.         actor currentActor = this;
  59.         while (! ((currentActor instanceof stage) || (currentActor == null))) {
  60.             currentActor = currentActor.container();
  61.         }
  62.         return (stage)currentActor;
  63.     }
  64.  
  65.     public int locklevel () { 
  66.         stage stage = stage();
  67.         if (stage != null) {
  68.             return stage().locklevel();
  69.         } else return 0; 
  70.     }
  71.  
  72.     public void lock () { 
  73.         stage stage = stage();
  74.         if (stage != null) {
  75.             stage.lock();
  76.         } 
  77.     }
  78.     public void unlock () { unlock(false); }
  79.     public void unlock (boolean force) { 
  80.         stage stage = stage();
  81.         if (stage != null) {
  82.             stage.unlock(force);
  83.         }
  84.     }
  85.         
  86.     public void forceredraw () {
  87.         stage stage = stage();
  88.         if (stage != null) {
  89.             stage.canvas().forceRepaint();
  90.         }
  91.     }
  92.     
  93.     private void addtodirtylist() {
  94.         stage stage = stage();
  95.         if (stage != null) {
  96.             stage.canvas().adddirtyactor(this);
  97.         }
  98.     }
  99.  
  100.     public void makedirty () {
  101.         stage stage = stage();
  102.         if (stage != null) {
  103.             stagecanvas curCanvas = stage.canvas();
  104.             if ((filldirty == 0) || (framedirty == 0)) {
  105.                 curCanvas.addRgnToUpdateRgn(this, boundsregion());
  106.             }
  107.             filldirty++;
  108.             framedirty++;
  109.             curCanvas.forceRepaint();
  110.         }
  111.     }
  112.     
  113.     public void makefilldirty() {
  114.         stage stage = stage();
  115.         if (stage != null) {
  116.             stagecanvas curCanvas = stage.canvas();
  117.             if (filldirty == 0) {
  118.                 curCanvas.addRgnToUpdateRgn(this, fillregion());
  119.             }
  120.             filldirty++;
  121.             curCanvas.forceRepaint();
  122.         }
  123.     }
  124.     
  125.     public void makeframedirty() {
  126.         stage stage = stage();
  127.         if (stage != null) {
  128.             stagecanvas curCanvas = stage.canvas();
  129.             if (framedirty == 0) {
  130.                 curCanvas.addRgnToUpdateRgn(this, frameregion());
  131.             }
  132.             framedirty++;
  133.             curCanvas.forceRepaint();
  134.         }
  135.     }
  136.     
  137.     //======================================================================
  138.     // Container and contents
  139.     //======================================================================
  140.     
  141.     protected list contentsVar = null;
  142.     public list contents () {
  143.         return contentsVar.copy();
  144.     }
  145.     
  146.     private actor containerVar = null;
  147.     public actor container () {
  148.         return containerVar;
  149.     }
  150.     public void setcontainer (actor act) {
  151.         actor oldcontainer = containerVar;
  152.         
  153.         if (oldcontainer != null) {
  154.             oldcontainer.contentsVar.removeElement(this);
  155.             oldcontainer.makedirty();
  156.             oldcontainer.lock();
  157.         }
  158.     
  159.         containerVar = act;
  160.         
  161.         if (act != null) {
  162.             act.lock();
  163.             act.contentsVar.push(this);
  164.             act.makedirty();
  165.             this.makedirty();
  166.         }
  167.         
  168.         if (oldcontainer != null) oldcontainer.unlock();
  169.         if (act != null) act.unlock();
  170.     }
  171.     
  172.     //======================================================================
  173.     // Layer
  174.     //======================================================================
  175.  
  176.     public int layer () {
  177.         actor mycontainer = this.container();
  178.         if (mycontainer == null) {
  179.             return 1;
  180.         } else {
  181.             int pos = mycontainer.contentsVar.position(this);
  182.             if (pos == -1)
  183.                 return 1;
  184.             else
  185.                 return pos;    
  186.         }
  187.     }
  188.     
  189.     public void setlayer (int newlayer) {
  190.         actor mycontainer = this.container();
  191.         list peers = mycontainer.contentsVar;
  192.         if (mycontainer != null) {
  193.             if (newlayer <= 0) newlayer = 1;            //bounds checking
  194.             int numactors = peers.length();                //bounds checking   
  195.             if (newlayer > numactors) newlayer = numactors;        //bounds checking
  196.         
  197.             if (newlayer != this.layer()) {                //if we are different then change the layer
  198.                 peers.removeElement(this);
  199.                 peers.insertnth(newlayer, this);
  200.                 this.makedirty();
  201.             }
  202.         }
  203.     }
  204.     
  205.     //Layer helper functions.
  206.     //Note that setlayer does all the required error checking.
  207.     public void bringtofront () {
  208.         this.setlayer(1);
  209.     }
  210.         
  211.     public void bringcloser () {
  212.         this.setlayer(this.layer() - 1);
  213.     }
  214.  
  215.     public void sendfurther () {
  216.         this.setlayer(this.layer() + 1);
  217.     }
  218.     
  219.     public void sendtoback () {
  220.         actor mycontainer = this.container();
  221.         if (mycontainer != null) {
  222.             this.setlayer(mycontainer.contentsVar.length());
  223.         }
  224.     }
  225.     
  226.     //======================================================================
  227.     // visible, hide and show. 
  228.     //======================================================================
  229.  
  230.     private boolean visibleVar = true;
  231.  
  232.     public boolean visible () {
  233.         return visibleVar;
  234.     }
  235.     
  236.     public void setvisible (boolean newvalue) {
  237.         visibleVar = newvalue;
  238.         makedirty();
  239.     }
  240.     
  241.     public void hide () {
  242.         if (visibleVar == true) setvisible(false);
  243.     }
  244.     public void show () {
  245.         if (visibleVar == false) setvisible(true);
  246.     }
  247.  
  248.     //======================================================================
  249.     // Boundsrect et.al.
  250.     //======================================================================
  251.  
  252.     public Object resized () {
  253.         return null;
  254.     }
  255.     public Object moved () {
  256.         return null;
  257.     }
  258.     
  259.     public Point physicaltological (Point location) {
  260.         actor currentActor = this;
  261.         Point containerLocation;
  262.         while (currentActor != null) {
  263.             if (currentActor instanceof stage) 
  264.                 containerLocation = new Point(0,0);
  265.             else 
  266.                 containerLocation = currentActor.location();
  267.             location.translate(- containerLocation.x, - containerLocation.y);
  268.             currentActor = currentActor.container();
  269.         }
  270.         return location;
  271.     }
  272.  
  273.     public Point logicaltophysical (Point location) {
  274.         actor currentActor = this;
  275.         Point containerLocation;
  276.         while (currentActor != null) {
  277.             if (currentActor instanceof stage) 
  278.                 containerLocation = new Point(0,0);
  279.             else 
  280.                 containerLocation = currentActor.location();
  281.             location.translate(containerLocation.x, containerLocation.y);
  282.             currentActor = currentActor.container();
  283.         }
  284.         return location;
  285.     }
  286.  
  287.     public Rectangle logicaltophysicalrect (Rectangle bounds) {
  288.         Point topleft = new Point(bounds.x, bounds.y);
  289.         this.logicaltophysical(topleft);
  290.         bounds.x = topleft.x;
  291.         bounds.y = topleft.y;
  292.         return bounds;
  293.     }
  294.     
  295.     
  296.     
  297.     private Rectangle boundsrectVar = new Rectangle(0,0,20,20);
  298.     
  299.     public Rectangle boundsrect () {
  300.         return new Rectangle(boundsrectVar.x, boundsrectVar.y, boundsrectVar.width, boundsrectVar.height);
  301.     }
  302.  
  303.     public Rectangle boundsrect (boolean physical) {
  304.         if (physical == true) {
  305.             Rectangle mybounds = this.boundsrect();
  306.             actor mycontainer = this.container();
  307.             if ((mycontainer != null) && (! (mycontainer instanceof stage)))
  308.                 mycontainer.logicaltophysicalrect(mybounds);
  309.             return mybounds;
  310.         } else
  311.             return this.boundsrect();
  312.     }
  313.  
  314.     
  315.     public void setboundsrect(int h, int v, int width, int height, boolean physical, boolean relative, boolean justmoving) {
  316.         int boundx, boundy, boundwidth, boundheight;
  317.         Rectangle mybounds = this.boundsrect();
  318.         if (relative == true) {
  319.             // if relative is true, physical does not matter since there is no scale. 
  320.             boundx = h + mybounds.x;
  321.             boundy = v + mybounds.y;
  322.             boundwidth = width + mybounds.width;
  323.             boundheight = height + mybounds.height;
  324.         } else {
  325.             if (physical == true) {
  326.                 // translate to logical. 
  327.                 Point logicalloc = new Point(h, v);
  328.                 actor mycontainer = this.container();
  329.                 if (mycontainer != null) 
  330.                     logicalloc = mycontainer.physicaltological(logicalloc);
  331.                 boundx = logicalloc.x;
  332.                 boundy = logicalloc.y;
  333.             } else {
  334.                 boundx = h;
  335.                 boundy = v;
  336.             }
  337.             boundwidth = width;
  338.             boundheight = height;
  339.         }
  340.         
  341.         // All set. Do the work to update the regions and the screen
  342.         this.lock();
  343.         this.makedirty();
  344.         this.addtodirtylist();
  345.         boundsrectVar = new Rectangle(boundx, boundy, boundwidth, boundheight);
  346.         if (justmoving == true) {
  347.             int xoffset = mybounds.x - boundx;
  348.             int yoffset = mybounds.y - boundy;
  349.             this.offsetDeeply(xoffset, yoffset);
  350.         } else this.regionsDirty = true;
  351.         this.unlock();
  352.     }
  353.     
  354.     //recursively offsets all of the inner contents regions by an x and y amount
  355.     private void offsetDeeply(int x, int y) {
  356.         this.offsetRegions(x, y);
  357.         list contents = this.contentsVar;
  358.         for(visitstate vs = contents.initialvisitstate(); vs != null; vs = contents.succeedingvisitstate(vs)) {
  359.             actor el = (actor) contents.elementatvisitstate(vs);
  360.             el.offsetDeeply(x, y);
  361.         }
  362.     }
  363.         
  364.     
  365.     public void setboundsrect (Rectangle r) {
  366.         this.setboundsrect(r.x, r.y, r.width, r.height, false, false, false);
  367.     }
  368.     
  369.     public void setboundsrect (int x, int y, int width, int height) {
  370.         this.setboundsrect(x, y, width, height, false, false, false);
  371.     }
  372.     public void setboundsrect (int x, int y, int width, int height, boolean physical) {
  373.         this.setboundsrect(x, y, width, height, physical, false, false);
  374.     }
  375.     
  376.     public void setboundsrect (collection bounds) {
  377.         setboundsrect(bounds, false, false);
  378.     }
  379.     public void setboundsrect (collection bounds ,boolean physical) {
  380.         setboundsrect(bounds, physical, false);
  381.     }
  382.     public void setboundsrect (collection bounds, boolean physical, boolean relative) {
  383.         int left = bounds.nthint(1);
  384.         int top = bounds.nthint(2);
  385.         int right = bounds.nthint(3);
  386.         int bottom = bounds.nthint(4);
  387.         this.setboundsrect(left, top, right - left, bottom - top, physical, relative, false);
  388.     }
  389.     
  390.     
  391.     // location. 
  392.     
  393.     public Point location () {
  394.         return this.location(false);
  395.     }
  396.     public Point location (boolean physical) {
  397.         Rectangle mybounds = this.boundsrect(physical);
  398.         return new Point (mybounds.x, mybounds.y);
  399.     }
  400.     
  401.     public void setlocation (int h, int v, boolean physical, boolean relative) {
  402.         int width, height;
  403.         if (relative) {
  404.             width = 0;
  405.             height = 0;
  406.         } else {
  407.             Dimension curSize = this.size();
  408.             width = curSize.width;
  409.             height = curSize.height;
  410.         }
  411.             
  412.         // call setboundsrect with justmoving = true.
  413.         this.setboundsrect(h, v, width, height, physical, relative, true);
  414.     }
  415.  
  416.     public void setlocation (Point location) {
  417.         this.setlocation(location.x, location.y, false, false);
  418.     }
  419.  
  420.     public void setlocation (Point location, boolean physical) {
  421.         this.setlocation(location.x, location.y, physical, false);
  422.     }
  423.  
  424.     public void setlocation (collection location) {
  425.         int h = location.nthint(1);
  426.         int v = location.nthint(2);
  427.         Dimension mysize = this.size();
  428.         int left = h - (mysize.width / 2);
  429.         int top = v - (mysize.height / 2);
  430.         this.setlocation(left, top, false, false);
  431.     }
  432.  
  433.     // size. Does not need to go through the boundsrect, but needs to because the user
  434.     // might redefine boundsrect to return esoteric values. Oh well... "SK8! Hooks everywhere!"
  435.  
  436.     public Dimension size () {
  437.         return this.size(false);
  438.     }
  439.     public Dimension size (boolean physical) {
  440.         Rectangle mybounds = this.boundsrect();
  441.         // since we are not implementing scale physical can be ignored. 
  442.         return new Dimension(mybounds.width, mybounds.height);
  443.     }
  444.     
  445.     // Size should preserve the location!!!
  446.     
  447.     public void setsize (int width, int height, boolean physical, boolean relative) {
  448.         Rectangle mybounds = this.boundsrect(physical);
  449.         int newleft, newtop;
  450.         if (relative == true) {
  451.             newleft = mybounds.x + (mybounds.width / 2) - (width + mybounds.width) / 2;
  452.             newtop = mybounds.y + (mybounds.height / 2) - (height + mybounds.height) / 2;
  453.             this.setboundsrect(newleft, newtop, width + mybounds.width, height + mybounds.height, physical, false, false);
  454.         } else {
  455.             newleft = mybounds.x + (mybounds.width / 2) - (width / 2);
  456.             newtop =  mybounds.y + (mybounds.height / 2) - (height / 2);
  457.             this.setboundsrect(newleft, newtop, width, height, physical, relative, false);
  458.         }
  459.     }
  460.     
  461.     public void setsize (int width, int height) {
  462.         this.setsize(width, height, false, false);
  463.     }
  464.     
  465.     public void setsize (collection size) {
  466.         int width = size.nthint(1);
  467.         int height = size.nthint(2);
  468.         this.setsize(width, height, false, false);
  469.     }
  470.  
  471.     // Functions for compatability with SK8
  472.     public list boundsrectlist () {
  473.         return boundsrectlist(false);
  474.     }
  475.  
  476.     public list boundsrectlist (boolean physical) {
  477.         Rectangle rr = boundsrect(physical);
  478.         return sk8.list(rr.x, rr.y, rr.x + rr.width, rr.y + rr.height);
  479.     }
  480.  
  481.     public void setboundsrectlist (collection bounds) {
  482.         setboundsrect(bounds, false, false);
  483.     }
  484.     public void setboundsrectlist (collection bounds ,boolean physical) {
  485.         setboundsrect(bounds, physical, false);
  486.     }
  487.     public void setboundsrectlist (collection bounds, boolean physical, boolean relative) {
  488.         setboundsrect(bounds, physical, relative);
  489.     }
  490.     
  491.     
  492.     public list locationlist () {
  493.         return locationlist(false);
  494.     }
  495.  
  496.     public list locationlist (boolean physical) {
  497.         Rectangle rr = boundsrect(physical);
  498.         int h =  rr.x + (rr.width / 2);
  499.         int v =  rr.y + (rr.height / 2);
  500.         return sk8.list(h, v);
  501.     }
  502.     public list sizelist () {
  503.         return sizelist(false);
  504.     }
  505.  
  506.     public list sizelist (boolean physical) {
  507.         Rectangle rr = boundsrect(physical);
  508.         return sk8.list(rr.width, rr.height);
  509.     }
  510.     
  511.     // Height and Width helper functions
  512.     public int width() {
  513.         return this.boundsrect().width;
  514.     }
  515.     public void setwidth(int w) {
  516.          setsize(w, this.boundsrect().height, false, false);
  517.     }
  518.     public int height() {
  519.         return this.boundsrect().height;
  520.     }
  521.     public void setheight(int h) {
  522.         setsize(this.boundsrect().width, h, false, false);
  523.     }
  524.  
  525.     // H and V helper functions for boundsrect
  526.     
  527.     public int h() {
  528.         Rectangle rr = this.boundsrect();
  529.         int res;
  530.         res =  rr.x + (rr.width / 2);
  531.         return res;
  532.     }
  533.     public void seth(int h) {
  534.          seth(h, false, false);
  535.     }
  536.     public void seth(int h, boolean physical) {
  537.          seth(h, physical, false);
  538.     }
  539.     public void seth(int h, boolean physical, boolean relative) {
  540.          setlocation(h, this.v(), physical, relative);
  541.     }
  542.     public int v() {
  543.         Rectangle rr = this.boundsrect();
  544.         int res;
  545.         res = rr.y + (rr.height / 2);
  546.         return res;
  547.     }
  548.     public void setv(int v) {
  549.          seth(v, false, false);
  550.     }
  551.     public void setv(int v, boolean physical) {
  552.          seth(v, physical, false);
  553.     }
  554.     public void setv(int v, boolean physical, boolean relative) {
  555.          setlocation(this.h(), v, physical, relative);
  556.     }
  557.     // Top, Right, Left, and Bottom helper functions  *****NEED SETTERS
  558.     public int top() {
  559.         return top(false);
  560.     }
  561.     public int top(boolean physical) {
  562.         return this.boundsrect(physical).y;
  563.     }
  564.     public int left() {
  565.         return left(false);
  566.     }
  567.     public int left(boolean physical) {
  568.         return this.boundsrect(physical).x;
  569.     }
  570.     public int bottom() {
  571.         return bottom(false);
  572.     }
  573.     public int bottom(boolean physical) {
  574.         Rectangle rr = this.boundsrect(physical);
  575.         return rr.y + rr.height;
  576.     }
  577.     public int right() {
  578.         return right(false);
  579.     }
  580.     public int right(boolean physical) {
  581.         Rectangle rr = this.boundsrect(physical);
  582.         return rr.x + rr.width;
  583.     }
  584.     
  585.     //======================================================================
  586.     // Highlight
  587.     //======================================================================
  588.  
  589.     
  590.     boolean highlightedVar = false;
  591.     public void dohighlight () {
  592.         this.lock();
  593.         this.setfillcolor(sk8.black);
  594.         this.settextcolor(sk8.white);
  595.         this.unlock();
  596.     }
  597.  
  598.     public void dounhighlight () {
  599.         this.lock();
  600.         this.setfillcolor(sk8.white);
  601.         this.settextcolor(sk8.black);
  602.         this.unlock();
  603.     }
  604.     
  605.     public boolean highlight () {
  606.         return this.highlightedVar;
  607.     }
  608.     
  609.     // very simple, change the fillcolor to the highlight color. 
  610.     // call dohighlight and dounhighlight to actually do it. This way
  611.     // people can redefine the method to get correct custom highlight
  612.     // behaviour. 
  613.     
  614.     public void sethighlight (boolean newvalue) {
  615.         if (newvalue != this.highlight()) {
  616.             this.highlightedVar = newvalue;
  617.             if (newvalue == true)
  618.                 this.dohighlight();
  619.             else
  620.                 this.dounhighlight();
  621.         }
  622.     }
  623.  
  624.  
  625.     boolean autohighlightVar = false;
  626.     public boolean autohighlight () {
  627.         return this.autohighlightVar;
  628.     }
  629.     
  630.     public void setautohighlight (boolean newvalue) {
  631.         this.autohighlightVar = newvalue;
  632.     }
  633.  
  634.     public void trackmousedown (actor originaltarget) {
  635.         this.sethighlight(true);
  636.         this.mousetrackingmode.originaltarget = originaltarget;
  637.         this.mousetrackingmode.entermode();
  638.     }
  639.  
  640.     //======================================================================
  641.     // Fillcolor
  642.     //======================================================================
  643.  
  644.     public renderer fillcolor () {
  645.         return fillcolorVar;
  646.     }
  647.     
  648.     public void setfillcolor (renderer ren) {
  649.         fillcolorVar = ren;
  650.         makefilldirty();
  651.     }
  652.     
  653.     //======================================================================
  654.     // Frame Stuff
  655.     //======================================================================
  656.  
  657.     public renderer framecolor () {
  658.         return framecolorVar;
  659.     }
  660.     
  661.     public void setframecolor (renderer ren) {
  662.         framecolorVar = ren;
  663.         makeframedirty();
  664.     }
  665.  
  666.     public int framesize () {
  667.         return framesizeVar;
  668.     }
  669.     public list framesizelist () {
  670.         return sk8.list(framesizeVar, framesizeVar);
  671.     }
  672.     
  673.     public void setframesize (int s) {
  674.         framesizeVar = s;
  675.         this.makedirty();
  676.         this.regionsDirty = true;  // HMM DONT NEED TO RECOMPUTE BOUNDS IN THIS CASE, BUT WE ARE...
  677.     }
  678.     
  679.     public void setframesize (list ll) {
  680.          int s = ll.nthint(1);
  681.         this.setframesize(s);
  682.     }
  683.  
  684.     //======================================================================
  685.     // Text
  686.     //======================================================================
  687.         
  688.     /* text */
  689.     public String text () {
  690.         if (textVar == null) {
  691.             textVar = "";
  692.         }
  693.         return textVar;
  694.     }
  695.     public void settext (String s) {
  696.         if (s == null) {
  697.             textVar = "";
  698.         } else {
  699.             textVar = s;
  700.         }
  701.         makefilldirty();
  702.     }
  703.     
  704.     /* textcolor */
  705.     public renderer textcolor () {
  706.         return textcolorVar;
  707.     }
  708.     public void settextcolor (renderer ren) {
  709.         if (ren instanceof rgbcolor) {
  710.             textcolorVar = ren;
  711.             makefilldirty();
  712.             }
  713.         else
  714.             throw new RuntimeException("text color can only be an rgbcolor for now.");
  715.     }
  716.  
  717.     /* textsize */
  718.     public int textsize () {
  719.         return textfontVar.getSize();
  720.     }
  721.     
  722.     public void settextsize (int s) {
  723.         textfontVar = new Font(textfontVar.getName(), textfontVar.getStyle(), s);
  724.         makefilldirty();
  725.     }
  726.  
  727.     /* textfont */
  728.     public String textfont () {
  729.         return textfontVar.getName();
  730.     }
  731.     public void settextfont (String name) {
  732.         textfontVar = new Font(name, textfontVar.getStyle(), textfontVar.getSize() );
  733.         makefilldirty();
  734.     }
  735.  
  736.     /* textstyle */
  737.     public int textstyle () {
  738.         return textfontVar.getStyle();
  739.     }
  740.     public void settextstyle (int s) {
  741.         textfontVar = new Font(textfontVar.getName(), s, textfontVar.getSize());
  742.         makefilldirty();
  743.     }
  744.     
  745.     public void settextstyle (list newvalue) {
  746.         //***NEED TO IMPLEMENT THIS!!!!
  747.         throw new RuntimeException("Not Implemented:  For now, set the text style to a JAVA style (an integer).");
  748.     }
  749.  
  750.     // textlocation.
  751.     
  752.     public symbol textlocation () {
  753.         return this.textlocationVar;
  754.     }
  755.     
  756.     public void settextlocation (symbol newvalue) {
  757.         this.textlocationVar = newvalue;
  758.         clearTextLocationInfo();
  759.         this.makefilldirty();
  760.     }
  761.     
  762.     // ActorTextSize
  763.  
  764.     public Point actortextsize () {
  765.         Graphics g = sk8.stage.canvas().getGraphics();
  766.         g.setFont(this.textfontVar);
  767.         return this.actortextsize(g);
  768.     }
  769.     
  770.     public Point actortextsize(Graphics g, String s, boolean ExcludeDescent) {
  771.         FontMetrics fm = g.getFontMetrics(this.textfontVar);
  772.         int height = fm.getHeight();
  773.         int width = fm.stringWidth(s);
  774.         if (ExcludeDescent == true) 
  775.             height -= fm.getDescent();
  776.         return new Point(width, height);
  777.     }
  778.     
  779.     public Point actortextsize(Graphics g, String s) {
  780.         return actortextsize(g, s, false);
  781.     }
  782.     public Point actortextsize(Graphics g) {
  783.         return actortextsize(g, textVar, false);
  784.     }
  785.     
  786.     public Point actortextsize(Graphics g, boolean ExcludeDescent) {
  787.         return actortextsize(g, textVar, ExcludeDescent);
  788.     }
  789.  
  790.  
  791.     //======================================================================
  792.     // Drawing
  793.     //======================================================================
  794.  
  795.     //-------------------------------------------------------------------------
  796.     //-------------------------------------------------------------------------
  797.  
  798.     public Region makeboundsregion() {
  799.         Region reg = new Region();
  800.         Rectangle myBR = boundsrect(true);
  801.         reg.setRectRegion(myBR.x, myBR.y, myBR.width, myBR.height);
  802.         return reg;
  803.     }
  804.     
  805.     public Region makefillregion() {
  806.         Region reg = new Region();
  807.         Rectangle myBR = boundsrect(true);
  808.         myBR.x += framesizeVar;
  809.         myBR.y += framesizeVar;
  810.         myBR.width -= 2 * framesizeVar;
  811.         myBR.height -= 2 * framesizeVar;
  812.         reg.setRectRegion(myBR.x, myBR.y, myBR.width, myBR.height);
  813.         return reg;
  814.     }
  815.     
  816.     public Region makeframeregion() {
  817.         if (framesizeVar > 0) {
  818.             Region br = boundsregion().copy();
  819.             br.diffRegion(fillregion());
  820.             return br;
  821.         } else {
  822.             return new Region();
  823.         }
  824.     }
  825.     
  826.     private void offsetRegions (int dx, int dy) {
  827.         if ((boundsregionVar != null) && (regionsDirty != true)) boundsregionVar.offsetRegion(dx,dy);
  828.         if ((fillregionVar != null) && (regionsDirty != true)) fillregionVar.offsetRegion(dx,dy);
  829.         if ((frameregionVar != null) && (regionsDirty != true)) frameregionVar.offsetRegion(dx,dy);
  830.     
  831.     }
  832.  
  833.     private Region boundsregionVar = null;
  834.     private boolean regionsDirty = true;
  835.     public Region boundsregion() {
  836.         if ((boundsregionVar == null) || (regionsDirty == true))
  837.             boundsregionVar = makeboundsregion();
  838.         return boundsregionVar;
  839.     }
  840.     
  841.     private Region fillregionVar = null;
  842.     public Region fillregion() {
  843.         if ((fillregionVar == null) || (regionsDirty == true)) {
  844.             fillregionVar = makefillregion();
  845.             clearTextLocationInfo();
  846.         }
  847.         return fillregionVar;
  848.     }
  849.     
  850.     private Region frameregionVar = null;
  851.     public Region frameregion() {
  852.         if ((frameregionVar == null) || (regionsDirty == true))
  853.             frameregionVar = makeframeregion();
  854.         return frameregionVar;
  855.     }
  856.  
  857.  
  858.     public void clipRegionToAllContainers (Region rgn) {
  859.         actor currentActor = this.container();
  860.         while (currentActor != null) {
  861.             rgn.sectRegion(currentActor.fillregion());
  862.             currentActor = currentActor.container();
  863.         }
  864.     }
  865.  
  866.     public void draw (Graphics g, Region drawRegion) {
  867.         filldirty = 0;
  868.         framedirty = 0;
  869.         
  870.         if ((visible() == true) && (! drawRegion.isEmptyRegion())) {
  871.                 
  872.             //Check to see if the frame is dirty
  873.             if (framesizeVar > 0) {
  874.                 Region frameToDraw = drawRegion.copy();
  875.                 frameToDraw.sectRegion(frameregion());
  876.                 //If so we render the part of it that intersects the draw region
  877.                 if (! frameToDraw.isEmptyRegion()) 
  878.                     framecolor().render(g, this, frameToDraw);
  879.             }
  880.             
  881.             //Now the Fill Region
  882.             //We check first to make sure it is dirty and needs drawing
  883.             //Note that since the fill is all that remains
  884.             //we can just the region object we were passed to do the rest of the work.
  885.             //therefore we don't have to make another copy like we did with the frame.
  886.             Region fillToDraw = drawRegion;
  887.             fillToDraw.sectRegion(fillregion());
  888.             
  889.             //If there is anything to draw..
  890.             if (! fillToDraw.isEmptyRegion()) {
  891.             
  892.                 // First draw the contents
  893.                 list contents = this.contentsVar;
  894.                 if (! contents.empty()) {
  895.                     for(visitstate vs = contents.initialvisitstate(); 
  896.                         ((vs != null) && (! drawRegion.isEmptyRegion()));
  897.                         vs = contents.succeedingvisitstate(vs)) {
  898.                             //For each subActor
  899.                         actor subActor = (actor) contents.elementatvisitstate(vs);
  900.                         //Generate a new draw region which is the part
  901.                         //that's over the subActor
  902.                         if ((subActor.visible() == true) && (subActor.boundsregion().bboxIntersects(drawRegion) == true)) {
  903.                             Region clippedDrawRegion = subActor.boundsregion().copy();
  904.                             clippedDrawRegion.sectRegion(drawRegion);
  905.                             //Then draw it
  906.                             subActor.draw(g, clippedDrawRegion);
  907.                             //And then remove that piece from our draw region
  908.                             drawRegion.diffRegion(subActor.boundsregion());
  909.                         }
  910.                     }
  911.                 }
  912.                 
  913.                 //Then the background 
  914.                 //Which is now the part of our fillregion that is not covered 
  915.                 //by things that needed to be drawn
  916.                 fillcolor().render(g, this, drawRegion);
  917.             }
  918.  
  919.             //And then the text overtop no matter what.
  920.             //**** We'd like to clip THIS to the draw region too, but cant yet...
  921.             if (this.text().length() > 0) 
  922.                 drawtext(g);
  923.             
  924.         }
  925.     }
  926.  
  927.     // This code computes the proper x, y location for the text to be drawn
  928.     // We optimize this by recomputing the point at draw time only after the setting 
  929.     // of textlocation and boundsrect and framesize
  930.     
  931.     private Point textLocDrawPoint;  // For storing the point
  932.     private void clearTextLocationInfo () {  //For signalling that the point needs to be recomputed
  933.         textLocDrawPoint = null;
  934.     }
  935.     
  936.     private void computeTextLocation (Graphics g) {
  937.         //Now we will compute the proper x, y location for the text to be drawn
  938.         int x = 0, y = 0;
  939.         
  940.         // First, we get the font information. All at one time, no need to call
  941.         // actortextsize.
  942.         FontMetrics fm = g.getFontMetrics(this.textfontVar);
  943.         int height = fm.getHeight();
  944.         int width = fm.stringWidth(this.textVar);
  945.         int descent = fm.getDescent();
  946.         int ascent = fm.getAscent();
  947.         
  948.         //Then, we compute the fill region's rectangle 
  949.         Rectangle myBR = boundsrect(true);
  950.  
  951.         // now deal with the nine cases for positioning.
  952.         if (this.textlocationVar == sk8.quote("TOPLEFT")) {
  953.             x = 3 + myBR.x;
  954.             y = myBR.y + height;
  955.         } else if (this.textlocationVar == sk8.quote("TOPCENTER")) {
  956.                 x = myBR.x + (myBR.width / 2) - (width / 2);
  957.                 y = myBR.y + ascent + 5; // height
  958.         } else if (this.textlocationVar == sk8.quote("TOPRIGHT")) {
  959.                 x = (myBR.x + myBR.width) - width;
  960.                 y = myBR.y + height;
  961.         } else if (this.textlocationVar == sk8.quote("CENTERLEFT")) {
  962.                 x = 3 + myBR.x;
  963.                 y = myBR.y + (myBR.height / 2); // - ((height + descent) / 2);
  964.         } else if (this.textlocationVar == sk8.quote("CENTER")) {
  965.                 x = myBR.x + (myBR.width / 2) - (width / 2);
  966.                 y = myBR.y + (myBR.height / 2) + descent;// - (height / 2);
  967.         } else if (this.textlocationVar == sk8.quote("CENTERRIGHT")) {
  968.                 x = (myBR.x + myBR.width) - width;
  969.                 y = myBR.y + (myBR.height / 2);// - ((height + descent) / 2);
  970.         } else if (this.textlocationVar == sk8.quote("BOTTOMLEFT")) {
  971.                 x = 3 + myBR.x;
  972.                 y = myBR.y + myBR.height - descent;
  973.         } else if (this.textlocationVar == sk8.quote("BOTTOMCENTER")) {
  974.                 x = myBR.x + (myBR.width / 2) - (width / 2);
  975.                 y = myBR.y + myBR.height - descent;
  976.         } else if (this.textlocationVar == sk8.quote("BOTTOMRIGHT")) {
  977.                 x = (myBR.x + myBR.width) - width;
  978.                 y = myBR.y + myBR.height - descent;
  979.         }
  980.         textLocDrawPoint = new Point(x, y);
  981.     }
  982.     
  983.     public void drawtext(Graphics curGraph) {
  984.         //First we remove any old clip regions
  985.         Graphics g = curGraph.create();
  986.         Rectangle myBR = fillregion().getBBox();
  987.         g.clipRect(myBR.x, myBR.y, myBR.width, myBR.height);
  988.                 
  989.         //And set up the textfont and text color
  990.         rgbcolor curtextcolor = (rgbcolor) this.textcolorVar;
  991.         g.setColor(curtextcolor.currentColor);
  992.         g.setFont(this.textfontVar);
  993.         
  994.         //Now compute the x, y location for the text to be drawn
  995.         if (textLocDrawPoint == null) 
  996.             computeTextLocation(g);
  997.         
  998.         // Now  finally draw the text draw the text!
  999.         g.drawString(textVar, textLocDrawPoint.x, textLocDrawPoint.y);
  1000.     }
  1001.  
  1002.  
  1003.     /*
  1004.  
  1005.         //======================================================================
  1006.     // Window Stuff
  1007.     //======================================================================
  1008.  
  1009.     String windowtitleVar = "";
  1010.     public String windowtitle () {
  1011.         return this.windowtitleVar;
  1012.     }
  1013.     
  1014.     public void setwindowtitle (String newvalue) {
  1015.         this.windowtitleVar = newvalue;
  1016.         if (this.container() == sk8.stage) {
  1017.             actorwindow curwindow = getwindow();
  1018.             if (curwindow != null) curwindow.setTitle(newvalue);
  1019.         }
  1020.     }
  1021.  
  1022.     int cursorVar= Frame.DEFAULT_CURSOR;
  1023.     public int cursor () {
  1024.         return this.cursorVar;
  1025.     }
  1026.     
  1027.     public void setcursor (int newvalue) {
  1028.         this.cursorVar = newvalue;
  1029.         if (this.container() == sk8.stage) {
  1030.             actorwindow curwindow = getwindow();
  1031.             if (curwindow != null) curwindow.setCursor(newvalue);
  1032.         }
  1033.     }
  1034.     */
  1035.  
  1036.         //======================================================================
  1037.     // MouseSensitivity
  1038.     //======================================================================
  1039.  
  1040.     symbol mousesensitivityVar = sk8.quote("NORMAL");
  1041.     
  1042.     public symbol mousesensitivity () {
  1043.         return this.mousesensitivityVar;
  1044.     }
  1045.     
  1046.     public void setmousesensitivity (symbol newvalue) {
  1047.         this.mousesensitivityVar = newvalue;
  1048.     }
  1049.  
  1050.         //======================================================================
  1051.     // DoFirstClick NEEDS TO BE IMPLEMENTED
  1052.     //======================================================================
  1053.  
  1054.     boolean dofirstclickVar = false; 
  1055.  
  1056.     public boolean dofirstclick () {
  1057.         return this.dofirstclickVar;
  1058.     }
  1059.     
  1060.     public void setdofirstclick (boolean newvalue) {
  1061.         this.dofirstclickVar = newvalue;
  1062.     }
  1063.  
  1064.  
  1065.         //======================================================================
  1066.     // Dispatching mouseenter and mouseleave... 
  1067.     //======================================================================
  1068.  
  1069.     // returns the depth of the actor in the containment hierarchy. If the
  1070.     // actor is not on the Stage, this returns 0. 
  1071.  
  1072.     public int depth () {
  1073.         actor anactor = this;
  1074.         int result = 1;
  1075.         while (true) {
  1076.             if ((anactor == null) || (anactor instanceof stage))
  1077.                 return result;
  1078.             result = result + 1;
  1079.             anactor = anactor.container();
  1080.         }
  1081.     }
  1082.     
  1083.     actor findcommoncontainer (actor shallowactor, int depthdelta) {
  1084.         actor deepactor = this;
  1085.         // [1] bring them to the same depth. 
  1086.         int i;
  1087.         for (i = 0; i < depthdelta; i++) {
  1088.             if (deepactor == null) return null;
  1089.             deepactor = deepactor.container();
  1090.         }
  1091.         // [2] search and return when equal.
  1092.         while (true) {
  1093.             if ((deepactor == sk8.stage) || (deepactor == null) || (shallowactor == null))
  1094.                 return sk8.stage;
  1095.             if (deepactor == shallowactor)
  1096.                 return deepactor;
  1097.             deepactor = deepactor.container();
  1098.             shallowactor = shallowactor.container();
  1099.         }
  1100.     }
  1101.     
  1102.     // call mouseenter on each item in the path from commoncontainer to this (the actor).
  1103.     // use recursion to make the reverse calling happen. 
  1104.  
  1105.     void reverseddispatchmouseenter (actor commoncontainer) {
  1106.         if (this != commoncontainer) {
  1107.             if ((this.container() != null) && (commoncontainer != null)) {
  1108.                 ((actor)(this.container())).reverseddispatchmouseenter(commoncontainer);
  1109.                 this.mouseenter();
  1110.             }
  1111.         }
  1112.     }
  1113.     
  1114.     // this = the old actor, the one that should get a mouseleave. 
  1115.     
  1116.     // This function dispatches mouseEnter and mouseLeave events. MouseLeave is sent to 
  1117.     // all actors from oldActor to the commonContainer (not including the commonContainer).
  1118.     // MouseEnter is sent to all actors on the path from the commonContainer (not including it) to 
  1119.     // newActor. 
  1120.     // An important side effect of all this is that for every actor except newActor, mouseEnter
  1121.     // will be called and the eventActor will not be itself!!! Also that mouseEnter 
  1122.     // cannot be propagated up the hierarchy.
  1123.  
  1124.     // MouseLeave is done from the bottom up and mouseEnter from the top down.
  1125.     
  1126.     void dispatchmouseenterandleave(actor newactor) {
  1127.         actor oldactor = this;
  1128.         int olddepth = ((actor) oldactor).depth();
  1129.         int newdepth = ((actor) newactor).depth();
  1130.         actor commoncontainer;
  1131.         // if the actor is no longer on the stage, do not send mouseleaves to it. 
  1132.         if (newdepth == 0) 
  1133.             ((actor)newactor).reverseddispatchmouseenter(sk8.stage);
  1134.         else {
  1135.             // [1] find common container.
  1136.             if (olddepth > newdepth)
  1137.                 commoncontainer = ((actor) oldactor).findcommoncontainer(newactor, olddepth - newdepth);
  1138.             else 
  1139.                 commoncontainer = ((actor) newactor).findcommoncontainer(oldactor, newdepth - olddepth);
  1140.             // [2] Dispatch mouseleave (from deepest up).
  1141.             while (true) {
  1142.                 if ((oldactor == commoncontainer) || (oldactor == null)) break;
  1143.                 oldactor.mouseleave();
  1144.                 oldactor = oldactor.container();
  1145.             }
  1146.             // [3] set the event actor.
  1147.             sk8.stage.eventactorVar = newactor;
  1148.             // [4] Dispatch mouseenter (from shallowest up).
  1149.             ((actor) newactor).reverseddispatchmouseenter(commoncontainer);
  1150.         }    
  1151.     }
  1152.     
  1153.     // When the oldActor was nil, we throw up our arms. We just set the eventActor and
  1154.     // dispatch mouseEnter to everything from the Stage up to the new actor.
  1155.  
  1156.     void justdomouseenters () {
  1157.         // [1] set the event actor.
  1158.         sk8.stage.eventactorVar = this;
  1159.         // [2] send the mouse enters.
  1160.         this.reverseddispatchmouseenter(sk8.stage);
  1161.     }
  1162.     
  1163.     // this is the new event target. 
  1164.     
  1165.     void changeeventactor () {
  1166.         if (sk8.stage.eventactorVar != null)
  1167.             ((actor)(sk8.stage.eventactorVar)).dispatchmouseenterandleave(this);
  1168.         else
  1169.             this.justdomouseenters();
  1170.     }
  1171.  
  1172.  
  1173.         //======================================================================
  1174.     // Event System
  1175.     //======================================================================
  1176.  
  1177.     
  1178.     // pointonwhichactor
  1179.     // Figuring out the event actor using mousesensitivity!!!
  1180.     // this = the window where we start the search. 
  1181.     // x and y are given in window coordinates. 
  1182.  
  1183.     public actor hitbymouse (int h, int v) {
  1184.         return null;
  1185.     }
  1186.     
  1187.     public actor pointonwhichactor (int x, int y) {
  1188.         return pointonwhichactor(x, y, null);
  1189.     }
  1190.     
  1191.     public actor pointonwhichactor (int x, int y, actor avoiding) {
  1192.         actor targethit = this;
  1193.         symbol mousesensitivity = this.mousesensitivity();
  1194.         if ((this.visible() == true) && 
  1195.             (this != avoiding) &&
  1196.             (mousesensitivity != sk8.quote("INVISIBLE")) &&
  1197.             (this.boundsregion().isInside(x,y))  //(this.boundsrect(true).inside(x,y)))
  1198.             ) {
  1199.                 // At this point actor has been physically hit. If it has custom mouse sensitivity,
  1200.                 // we call its method to find out who has been hit. The custom method handles
  1201.                 // examining the contents and thus we jump this step in this case.
  1202.                 if (mousesensitivity == sk8.quote("CUSTOM")) {
  1203.                     targethit = this.hitbymouse(x,y); 
  1204.                 } else {
  1205.                     // Does it pass mouse events and does it have contents to pass them to?
  1206.                       // and it does not have custom sensitivity.
  1207.                       if ((mousesensitivity != sk8.quote("OPAQUE")) && (! this.contentsVar.empty())) {
  1208.                     // YES: check each actor in contents.
  1209.                     
  1210.                     list contents = this.contentsVar;
  1211.                     for(visitstate vs = contents.initialvisitstate(); vs != null; vs = contents.succeedingvisitstate(vs)) {
  1212.                         actor thing = (actor) contents.elementatvisitstate(vs);
  1213.                             actor contenthit = thing.pointonwhichactor(x, y, avoiding);
  1214.                             if (contenthit != null) return contenthit;
  1215.                         }
  1216.                    }
  1217.             }
  1218.                 // if we got here, no subactor was hit. Then this actor is the most
  1219.                 // specific actor hit and we are done. We return it, unless it is mouseTransparent.
  1220.             if ((targethit != null) && (mousesensitivity != sk8.quote("TRANSPARENT"))) {
  1221.                 return targethit;
  1222.             }
  1223.         }
  1224.         return null;
  1225.     }
  1226.             
  1227.             
  1228.     // Event handlers. 
  1229.     
  1230.     void sk8idleevent (Event e) {
  1231.     }
  1232.     
  1233.     void sk8selectoldwindow (Event e, actor previouswindow) {
  1234.         if (previouswindow != null)
  1235.             previouswindow.deactivate();
  1236.         if (sk8.eventwindow() != null)
  1237.             sk8.eventwindow().activate();
  1238.     }
  1239.     
  1240.     void sk8mousedownevent (Event e) {
  1241.         actor curEventActor = sk8.eventactor();
  1242.         if (curEventActor != null) {
  1243.             //actor eventtarget = this.window().pointonwhichactor(sk8.stage.eventh(), sk8.stage.eventv());
  1244.             if (debug) sk8.sendtolog("Actor found at [" + sk8.eventh() + "," + sk8.eventv() + "] was " + curEventActor);
  1245.             curEventActor.mousedown();
  1246.             // Send clicks and doubleclicks: doubleclickstyle = 'normal'.
  1247.             if (e.clickCount == 1) {
  1248.                 curEventActor.click();
  1249.             } else if (e.clickCount == 2) {
  1250.                 curEventActor.click();
  1251.                 curEventActor.doubleclick();
  1252.             }
  1253.         }
  1254.     }
  1255.     
  1256.     void sk8mouseupevent (Event e) {
  1257.         if (sk8.eventactor() != null)
  1258.             sk8.eventactor().mouseup();
  1259.     }
  1260.     
  1261.     void sk8keydownevent (Event e) {
  1262.         if (sk8.eventactor() != null)
  1263.             sk8.eventactor().keydown((char) e.key);
  1264.     }
  1265.     
  1266.     void sk8keyupevent (Event e) {
  1267.         if (sk8.eventactor() != null)
  1268.             sk8.eventactor().keyup((char) e.key);
  1269.     }
  1270.                 
  1271.  
  1272.  
  1273.     // High level actor handlers: standard SK8 Suite. 
  1274.     
  1275.     public Object mouseenter () {
  1276.         // do NOT pass to the container!!!
  1277.         return null;
  1278.     }
  1279.     
  1280.     public Object mouseleave () {
  1281.         // do NOT pass to the container!!!
  1282.         return null;
  1283.     }
  1284.     
  1285.     public Object mousedown () {
  1286.         // do autohighlight behaviour. 
  1287.         if (this.autohighlight() == true) 
  1288.             trackmousedown(this);
  1289.         // propagate up the containment hierarchy. 
  1290.         actor mycontainer = this.container();
  1291.         if (mycontainer != null) {
  1292.             mycontainer.mousedown();
  1293.         }
  1294.         return null;
  1295.     }
  1296.     
  1297.     public Object mouseup () {
  1298.         actor mycontainer = this.container();
  1299.         if (mycontainer != null) {
  1300.             mycontainer.mouseup();
  1301.         }
  1302.         return null;
  1303.     }
  1304.  
  1305.     public Object click () {
  1306.         actor mycontainer = this.container();
  1307.         if (mycontainer != null) {
  1308.             mycontainer.click();
  1309.         }
  1310.         return null;
  1311.     }
  1312.  
  1313.     public Object doubleclick () {
  1314.         actor mycontainer = this.container();
  1315.         if (mycontainer != null) {
  1316.             mycontainer.doubleclick();
  1317.         }
  1318.         return null;
  1319.     }
  1320.  
  1321.     public Object keyup (char thekey) {
  1322.         return null;
  1323.     }
  1324.                 
  1325.     public Object keydown (char thekey) {
  1326.         return null;
  1327.     }
  1328.     
  1329.     public Object activate () {
  1330.         return null;
  1331.     }
  1332.     
  1333.     public Object deactivate () {
  1334.         return null;
  1335.     }
  1336.         
  1337.     //======================================================================
  1338.     // Dragging.
  1339.     //======================================================================
  1340.       
  1341.     public Object drag () {
  1342.         return this.drag(false);
  1343.     }
  1344.     public Object drag (boolean withEvents) {
  1345.         dragresizeeventmode em = new dragresizeeventmode(this, false, withEvents);
  1346.         em.entermode();
  1347.         return null;
  1348.     }
  1349.     
  1350.     public Object dragged () {
  1351.         return null;
  1352.     }
  1353.     public Object draggingmousewithin (actor actordragged) {
  1354.         return null;
  1355.     }
  1356.     public Object draggingmouseenter (actor actordragged) {
  1357.         return null;
  1358.     }
  1359.     public Object draggingmouseleave (actor actordragged) {
  1360.         return null;
  1361.     }
  1362.     public Object drop (actor droprecipient) {
  1363.         droprecipient.dropped(this);
  1364.         return null;
  1365.     }
  1366.     public Object dropped (actor droppee) {
  1367.         return null;
  1368.     }
  1369.  
  1370.  
  1371.     //======================================================================
  1372.     // RESIZING
  1373.     //======================================================================
  1374.       
  1375.     boolean resizableVar = true;
  1376.     public boolean resizable () {
  1377.         return this.resizableVar;
  1378.     }
  1379.     
  1380.     public void setresizable (boolean resi) {
  1381.         this.resizableVar = resi;
  1382.     }
  1383.                
  1384.     public Object resize () {
  1385.         return resize(sk8.quote("BOTTOMRIGHT"));  
  1386.     }
  1387.     
  1388.     public Object resize (symbol loc) {
  1389.         dragresizeeventmode em = new dragresizeeventmode(this, true, false);
  1390.         em.entermode();
  1391.         return null;  
  1392.     }
  1393.  
  1394.     public Object resizedone () {
  1395.         return null;
  1396.     }
  1397.     
  1398. }